Skip to content

[dashboard] feat: add auto_update_always toggle to client settings#580

Merged
heisbrot merged 3 commits intomainfrom
feature/auto-update-force
Mar 16, 2026
Merged

[dashboard] feat: add auto_update_always toggle to client settings#580
heisbrot merged 3 commits intomainfrom
feature/auto-update-force

Conversation

@pappz
Copy link
Copy Markdown
Contributor

@pappz pappz commented Mar 9, 2026

Add "Always Update" toggle to the Clients settings tab that controls whether updates are installed automatically in the background or require user interaction from the UI. Includes a warning icon and caution callout when enabled to highlight the risk of disrupting active connections.

localhost_3000_settings_tab=clients (2)

Summary by CodeRabbit

  • New Features
    • Added an "Always Update" toggle to Automatic Updates, letting users force automatic installs when permitted.
    • Toggle is disabled when automatic updates are not allowed or the chosen update method is disabled.
    • Shows a prominent warning callout when "Always Update" is enabled but the update method isn’t fully enabled.
    • Updated help text and save flow so the setting is stored with account preferences.

Add "Always Update" toggle to the Clients settings tab that controls
whether updates are installed automatically in the background or require
user interaction from the UI. Includes a warning icon and caution callout
when enabled to highlight the risk of disrupting active connections.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b29b74c-0558-41dd-b67c-de7945831bf2

📥 Commits

Reviewing files that changed from the base of the PR and between 6958bb5 and 548ee66.

📒 Files selected for processing (1)
  • src/modules/settings/ClientSettingsTab.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/modules/settings/ClientSettingsTab.tsx

📝 Walkthrough

Walkthrough

Adds a new boolean setting auto_update_always to Account.settings and surfaces it in the Client Settings UI with state, save integration, a toggle control, and a conditional warning callout.

Changes

Cohort / File(s) Summary
Account Interface
src/interfaces/Account.ts
Added auto_update_always: boolean to Account.settings.
Client Settings UI
src/modules/settings/ClientSettingsTab.tsx
Added autoUpdateAlways state initialized from account settings, integrated into change detection and save payload (PUT /accounts/:id), introduced FancyToggleSwitch UI with AlertTriangle icon and conditional Callout, and updated automatic-updates help text.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Client
    participant Server
    participant Database

    User->>Client: Toggle "Always Update"
    Client->>Client: set autoUpdateAlways, mark hasChanges
    User->>Client: Click "Save"
    Client->>Server: PUT /accounts/:id { settings: {..., auto_update_always } }
    Server->>Database: persist Account.settings.auto_update_always
    Database-->>Server: ack
    Server-->>Client: 200 OK (updated account)
    Client->>Client: update UI state, clear hasChanges, trigger updateRef
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • heisbrot

Poem

"I flipped the switch with a twitch and a hop,
updates march forward — I never stop.
A triangle blinks, a callout hums bright,
the rabbit approves: keep everything right. 🥕🐰"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: adding an auto_update_always toggle to client settings. It is concise, clear, and directly reflects the primary modification shown in both the interface definition and UI component changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/auto-update-force
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/interfaces/Account.ts (1)

29-29: Consider making auto_update_always optional for backwards compatibility.

Other recently added settings like peer_expose_enabled, network_range, and local_auth_disabled use the optional modifier (?). If existing accounts don't have this field persisted yet, the API may return undefined.

The consuming code already handles this defensively with account.settings?.auto_update_always ?? false, but the type should reflect the actual API contract.

Suggested change
-    auto_update_always: boolean;
+    auto_update_always?: boolean;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/interfaces/Account.ts` at line 29, The Account interface's
auto_update_always field is declared as required but the API can return
undefined; make auto_update_always optional to match other recent settings and
the consuming code's defensive checks. Update the Account interface by changing
the auto_update_always property to optional (like peer_expose_enabled,
network_range, local_auth_disabled) so its type is boolean | undefined and
ensure any references to Account.settings?.auto_update_always continue to use
the existing nullish coalescing handling.
src/modules/settings/ClientSettingsTab.tsx (1)

277-307: Simplify state reset logic when disabling auto-updates for better UX consistency.

When autoUpdateMethod changes to "disabled", the autoUpdateAlways state is not reset. This means the save payload includes auto_update_always: true even when updates are disabled, and re-enabling updates restores "Always Update" without explicit user action.

To align with the existing pattern used for autoUpdateCustomVersion, consider resetting autoUpdateAlways when updates are disabled:

Suggested refactor
const handleUpdateMethodChange = (value: string) => {
  setAutoUpdateMethod(value);
  if (value === "disabled" || value === "latest") {
    setAutoUpdateCustomVersion("");
  }
+ if (value === "disabled") {
+   setAutoUpdateAlways(false);
+ }
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/settings/ClientSettingsTab.tsx` around lines 277 - 307, In
ClientSettingsTab, ensure autoUpdateAlways is cleared when autoUpdateMethod
becomes "disabled": add a useEffect inside the ClientSettingsTab component that
watches autoUpdateMethod and, when it === "disabled", calls
setAutoUpdateAlways(false) (mirroring the existing reset for
autoUpdateCustomVersion) so the save payload no longer contains
auto_update_always:true while updates are disabled and toggling the method
restores the correct initial state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/interfaces/Account.ts`:
- Line 29: The Account interface's auto_update_always field is declared as
required but the API can return undefined; make auto_update_always optional to
match other recent settings and the consuming code's defensive checks. Update
the Account interface by changing the auto_update_always property to optional
(like peer_expose_enabled, network_range, local_auth_disabled) so its type is
boolean | undefined and ensure any references to
Account.settings?.auto_update_always continue to use the existing nullish
coalescing handling.

In `@src/modules/settings/ClientSettingsTab.tsx`:
- Around line 277-307: In ClientSettingsTab, ensure autoUpdateAlways is cleared
when autoUpdateMethod becomes "disabled": add a useEffect inside the
ClientSettingsTab component that watches autoUpdateMethod and, when it ===
"disabled", calls setAutoUpdateAlways(false) (mirroring the existing reset for
autoUpdateCustomVersion) so the save payload no longer contains
auto_update_always:true while updates are disabled and toggling the method
restores the correct initial state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b11ac19-71af-468f-891e-0e828bd270ad

📥 Commits

Reviewing files that changed from the base of the PR and between 10a8e7b and e7f38dc.

📒 Files selected for processing (2)
  • src/interfaces/Account.ts
  • src/modules/settings/ClientSettingsTab.tsx

Copy link
Copy Markdown
Contributor

@heisbrot heisbrot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

We should update the description for automatic updates. Currently, it is not clear that it requires manual user interaction.

The Always Update toggle is not very clear. Maybe "Enable Silent Updates" / "Enable Unattended Updates" / "Force Automatic Updates" or something like that?

The callout inside the Always Update toggle looks strange. We can remove "This may interrupt..." sentence from the toggle switch and move the callout below the switch (show the callout only when always update is enabled, as it currently is the case)

Clarify that automatic updates require user interaction by updating the
description. Rename "Always Update" to "Force Automatic Updates" for
clarity. Move warning callout below the toggle switch instead of inside it.
@pappz pappz requested a review from heisbrot March 12, 2026 15:49
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/modules/settings/ClientSettingsTab.tsx`:
- Around line 89-91: The autoUpdateAlways state (autoUpdateAlways /
setAutoUpdateAlways) is never cleared when the update method is set to
"disabled", causing auto_update_always to be restored incorrectly; update the
component so that whenever account.settings?.auto_update_version (or the local
update method state) becomes "disabled" you call setAutoUpdateAlways(false) to
normalize the UI, and also ensure the save payload sent from the save handler
clears/persists auto_update_always as false when auto_update_version ===
"disabled" so the backend cannot store a true value alongside a disabled update
method.
- Around line 247-249: The UI text in ClientSettingsTab contains contradictory
copy about automatic updates; update the copy to match the selected "force"
toggle state: locate the descriptive strings rendered in the ClientSettingsTab
component for automatic updates (the paragraphs currently explaining "prompted
to install" and "install automatically") and make them conditional on the force
toggle state variable (e.g., when force is true show the automatic-installation
wording, when false show the user-prompt wording). Ensure both places that
display the automatic-update description use the same conditional text logic so
they never contradict each other.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 85e8f9d6-b86a-4760-b920-8c256de6a5d7

📥 Commits

Reviewing files that changed from the base of the PR and between e7f38dc and 6958bb5.

📒 Files selected for processing (1)
  • src/modules/settings/ClientSettingsTab.tsx

Comment on lines +89 to +91
const [autoUpdateAlways, setAutoUpdateAlways] = useState(
account.settings?.auto_update_always ?? false,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Normalize autoUpdateAlways when auto updates are disabled.

This state is restored from Line 90 and always persisted again on Line 165, but nothing clears it when the update method becomes "disabled". A user can save auto_update_version: "disabled" together with auto_update_always: true, and after reload the force toggle comes back on but disabled.

💡 Suggested fix
   const [autoUpdateAlways, setAutoUpdateAlways] = useState(
-    account.settings?.auto_update_always ?? false,
+    account.settings?.auto_update_version !== "disabled" &&
+      (account.settings?.auto_update_always ?? false),
   );
   const handleUpdateMethodChange = (value: string) => {
     setAutoUpdateMethod(value);
     if (value === "disabled" || value === "latest") {
       setAutoUpdateCustomVersion("");
     }
+    if (value === "disabled") {
+      setAutoUpdateAlways(false);
+    }
   };
             ...account.settings,
             auto_update_version: autoUpdateCustomVersion || autoUpdateMethod,
-            auto_update_always: autoUpdateAlways,
+            auto_update_always:
+              autoUpdateMethod === "disabled" ? false : autoUpdateAlways,
             peer_expose_enabled: peerExposeEnabled,

Also applies to: 164-166

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/settings/ClientSettingsTab.tsx` around lines 89 - 91, The
autoUpdateAlways state (autoUpdateAlways / setAutoUpdateAlways) is never cleared
when the update method is set to "disabled", causing auto_update_always to be
restored incorrectly; update the component so that whenever
account.settings?.auto_update_version (or the local update method state) becomes
"disabled" you call setAutoUpdateAlways(false) to normalize the UI, and also
ensure the save payload sent from the save handler clears/persists
auto_update_always as false when auto_update_version === "disabled" so the
backend cannot store a true value alongside a disabled update method.

Comment on lines +247 to +249
Configure how NetBird clients receive update notifications.
When enabled, users will be prompted to install the selected
version. Automatic Updates require at least NetBird{" "}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

The new automatic-update copy contradicts itself.

Lines 247-249 say enabled updates prompt the user to install, while Lines 287-289 say they install automatically without user interaction. When the force toggle is on, both statements are shown together.

✏️ Possible wording
-              Configure how NetBird clients receive update notifications.
-              When enabled, users will be prompted to install the selected
-              version. Automatic Updates require at least NetBird{" "}
+              Configure how NetBird clients receive updates. By default, users
+              are prompted to install the selected version, or you can enable
+              Force Automatic Updates below to install it in the background.
+              Automatic Updates require at least NetBird{" "}

Also applies to: 287-289

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/settings/ClientSettingsTab.tsx` around lines 247 - 249, The UI
text in ClientSettingsTab contains contradictory copy about automatic updates;
update the copy to match the selected "force" toggle state: locate the
descriptive strings rendered in the ClientSettingsTab component for automatic
updates (the paragraphs currently explaining "prompted to install" and "install
automatically") and make them conditional on the force toggle state variable
(e.g., when force is true show the automatic-installation wording, when false
show the user-prompt wording). Ensure both places that display the
automatic-update description use the same conditional text logic so they never
contradict each other.

heisbrot
heisbrot previously approved these changes Mar 12, 2026
Comment thread src/modules/settings/ClientSettingsTab.tsx Outdated
Co-authored-by: Eduard Gert <kontakt@eduardgert.de>
@heisbrot heisbrot merged commit bad057d into main Mar 16, 2026
4 checks passed
@heisbrot heisbrot deleted the feature/auto-update-force branch March 16, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants